import os
import sys
from tkinter import Tk, simpledialog, filedialog, Toplevel, Label, Button, Entry, Scrollbar, Text, END

# 添加一个全局变量来控制调试信息的打印
DEBUG_MODE = True

def debug_print(message):
    if DEBUG_MODE:
        print(message)

def search_files_by_keywords(directory, keywords, max_depth, update_label, base_files=None):
    matching_files = []
    allowed_extensions = ['.zip', '.rar', '.7z']  # 允许的文件扩展名
    base_depth = len(directory.split(os.sep))  # 计算基础深度
    try:
        # 如果提供了 base_files，则只在这些文件中搜索
        if base_files:
            for file_path in base_files:
                update_label(f"正在检索文件: {file_path}")
                debug_print(f"调试信息: 检索文件: {file_path}")
                file_lower = os.path.basename(file_path).lower()
                # 检查文件扩展名是否符合要求
                if not any(file_lower.endswith(ext) for ext in allowed_extensions):
                    continue
                if all(keyword.lower() in file_lower for keyword in keywords):
                    matching_files.append(file_path)
        else:
            # 使用栈记录需要处理的文件夹及其深度
            stack = [(directory, 0)]  # 初始路径深度为 0

            while stack:
                current_dir, current_depth = stack.pop()
                relative_depth = current_depth + len(current_dir.split(os.sep)) - base_depth
                debug_print(f"调试信息: 当前目录: {current_dir}, 相对深度: {relative_depth}")

                # 如果超过最大深度，则跳过
                if relative_depth > max_depth:
                    debug_print(f"调试信息: 跳过目录（超过最大深度）: {current_dir}")
                    continue

                try:
                    # 获取当前目录的文件和子目录
                    with os.scandir(current_dir) as entries:
                        for entry in entries:
                            if entry.is_dir():
                                # 如果是子目录，压入栈并增加深度
                                stack.append((entry.path, current_depth + 1))
                                debug_print(f"调试信息: 发现子目录: {entry.path}, 深度: {current_depth + 1}")
                                # 检查文件夹名是否符合要求
                                if all(keyword.lower() in entry.name.lower() for keyword in keywords):
                                    matching_files.append(entry.path)
                            elif entry.is_file():
                                # 如果是文件，处理文件
                                current_file = entry.path
                                update_label(f"正在检索文件: {current_file}")
                                debug_print(f"调试信息: 检索文件: {current_file}")
                                file_lower = entry.name.lower()
                                # 检查文件扩展名是否符合要求
                                if not any(file_lower.endswith(ext) for ext in allowed_extensions):
                                    continue
                                if all(keyword.lower() in file_lower for keyword in keywords):
                                    matching_files.append(current_file)
                except PermissionError:
                    debug_print(f"调试信息: 无法访问目录: {current_dir}")
    except Exception as e:
        debug_print(f"调试信息: 搜索过程中发生错误: {e}")
    return matching_files

def get_search_criteria():
    def add_keyword(logic_type):
        entry = Entry(keyword_frame, width=40)
        entry.pack(pady=2)
        keyword_entries.append((entry, logic_type))

    def confirm():
        try:
            # Collect keywords and logic
            for entry, logic_type in keyword_entries:
                value = entry.get().strip()
                if value:
                    keywords.append((value, logic_type))

            # Collect max depth
            depth_value = depth_entry.get().strip()
            if depth_value.isdigit():
                max_depth.append(int(depth_value))
            else:
                debug_print("调试信息: 搜索层数输入无效")
                max_depth.append(None)

            debug_print(f"调试信息: 收集到的关键字和逻辑: {keywords}")
            debug_print(f"调试信息: 收集到的搜索层数: {max_depth[0]}")

            # Exit the event loop
            root.quit()
        except Exception as e:
            debug_print(f"调试信息: 确认时发生错误: {e}")

    def on_close():
        """Handle the close event for the search criteria window."""
        debug_print("搜索条件窗口已关闭。")
        root.quit()
        root.destroy()
        sys.exit()  # Ensure the program exits completely

    root = Toplevel()
    root.title("输入搜索条件")

    # Set the close event handler
    root.protocol("WM_DELETE_WINDOW", on_close)

    # Frame for keywords
    keyword_frame = Label(root, text="请输入关键字:", font=("Arial", 12))
    keyword_frame.pack(pady=10)

    keyword_entries = []
    keywords = []

    # Add initial keyword input
    add_keyword("与")

    button_frame = Label(root)
    button_frame.pack(pady=10)

    Button(button_frame, text="增加与关键字", command=lambda: add_keyword("与")).pack(side="left", padx=5)
    Button(button_frame, text="增加或关键字", command=lambda: add_keyword("或")).pack(side="left", padx=5)

    # Frame for max depth
    depth_frame = Label(root, text="请输入搜索层数 (0 表示仅当前目录):", font=("Arial", 12))
    depth_frame.pack(pady=10)

    depth_entry = Entry(root, width=40)
    depth_entry.pack(pady=5)

    # Confirm button
    Button(root, text="确认", command=confirm, bg="lightblue").pack(pady=10)

    max_depth = []
    root.mainloop()  # Start the event loop
    root.destroy()  # Destroy the window after the event loop exits

    return keywords, max_depth[0]

def show_results(results, restart_callback):
    try:
        debug_print("调试信息: 正在创建结果窗口...")
        result_window = Toplevel()
        result_window.title("搜索结果")
        result_window.configure(bg="#f5f5f5")

        # 允许窗口大小调整
        result_window.resizable(True, True)

        def on_close():
            debug_print("结果窗口已关闭。")
            result_window.destroy()
            root.quit()  # 关闭结果窗口时退出主循环

        # Set the close event handler
        result_window.protocol("WM_DELETE_WINDOW", on_close)

        Label(result_window, text="搜索结果:", font=("Arial", 14), bg="#f5f5f5").pack(pady=10)

        # Scrollable text area for results
        text_area = Text(result_window, wrap="word", width=80, height=20)
        text_area.pack(padx=10, pady=10, fill="both", expand=True)

        scrollbar = Scrollbar(result_window, command=text_area.yview)
        scrollbar.pack(side="right", fill="y")
        text_area.config(yscrollcommand=scrollbar.set)

        # Insert results into the text area
        if results:
            debug_print(f"调试信息: 搜索结果数量: {len(results)}")
            for file_path in results:
                text_area.insert(END, file_path + "\n")
        else:
            debug_print("调试信息: 未找到符合条件的文件。")
            text_area.insert(END, "未找到符合条件的文件。\n")

        text_area.config(state="disabled")  # Make the text area read-only

        # Restart button
        Button(result_window, text="重新开始", command=lambda: [result_window.destroy(), restart_callback()],
               bg="#4CAF50", fg="white", font=("Arial", 12)).pack(pady=10)

        debug_print("调试信息: 结果窗口已成功创建。")
    except Exception as e:
        debug_print(f"调试信息: 创建结果窗口时发生错误: {e}")

def main():
    def restart():
        root.destroy()  # 确保主窗口被销毁，避免残留
        main()

    def on_close():
        """Handle the close event for the main window."""
        debug_print("程序已关闭。")
        root.quit()  # 使用 quit 退出主循环
        root.destroy()
        sys.exit()  # 确保程序完全退出

    # Create the root Tkinter window
    global root  # 确保 root 是全局变量，便于在其他地方销毁
    root = Tk()
    root.withdraw()  # Hide the root window initially

    # Set the close event handler
    root.protocol("WM_DELETE_WINDOW", on_close)

    debug_print("请选择一个文件夹进行搜索...")
    selected_directory = filedialog.askdirectory(title="选择文件夹")

    if not selected_directory:
        debug_print("未选择文件夹，程序退出。")
        root.quit()
        root.destroy()
        return

    debug_print(f"调试信息: 选择的文件夹路径: {selected_directory}")

    # Get search criteria
    keywords_and_logic, max_depth = get_search_criteria()

    if not keywords_and_logic or max_depth is None:
        debug_print("未输入搜索条件，程序退出。")
        root.quit()
        root.destroy()
        return

    # 提取所有关键字
    keywords = [kw for kw, _ in keywords_and_logic]

    # Create a new window to display the current file being checked
    progress_window = Toplevel()
    progress_window.title("搜索进度")
    progress_window.configure(bg="#f5f5f5")
    progress_label = Label(progress_window, text="正在准备搜索...", font=("Arial", 12), bg="#f5f5f5")
    progress_label.pack(padx=20, pady=20)

    def update_label(text):
        progress_label.config(text=text)
        progress_window.update()

    # 搜索文件
    results = []
    try:
        debug_print("调试信息: 开始搜索关键字...")
        results = search_files_by_keywords(selected_directory, keywords, max_depth, update_label)
    except Exception as e:
        debug_print(f"调试信息: 搜索过程中发生错误: {e}")
    finally:
        # Ensure progress window is destroyed after search
        progress_window.destroy()

    # Show results in a new window
    debug_print("调试信息: 搜索完成，准备显示结果窗口...")
    show_results(results, restart)

    # Keep the main loop running
    try:
        root.mainloop()
    except KeyboardInterrupt:
        debug_print("调试信息: 主循环被中断。")
        root.quit()
        root.destroy()
        sys.exit()

if __name__ == "__main__":
    main()